#ifndef __RTRT_SCENEMGR_H__
#define __RTRT_SCENEMGR_H__

#include "Prerequisite.h"
#include "Singleton.h"
#include "AxisAlignedBox.h"

#define MAX_TREE_DEPTH 20

namespace RTRT
{
    class SceneManager : public Singleton<SceneManager>
    {
    public:
        SceneManager();
        ~SceneManager();

        int initScene();
        
        // Return root node of the kd-tree
        KDTreeNode *buildKDTree();
        
        // Sud-divide routine, will be recursively called when the kd-tree is being built
        void subDivide(const KTTreeNode *node, const AxisAlignedBox& aabb, int depth, size_t sceneObjCount);
    
		KDTreeNode *createKDTreeNodePairImpl();
		KDTreeNode *createKDTreeNodeImpl() {
			return new KDTreeNode;
		}
		
        // Create a pair of tree nodes
        KDTreeNode *createKDTreeNodePair();
        
		// Create a single tree node
		KDTreeNode *createKDTreeNode() {
			return createKDTreeNodeImpl();
		}
	
		AABB &getRootAABB() {
			return m_aabb;
		}
		
		KDTreeNode *getRootNode() {
			return m_rootNode;
		}
		
		void insertSplitPlane(const float splitPos);
		
		// Return the numbers of the lights
		size_t countLights() {
			return (size_t)m_lightArray.size();
		}
		
		Light *getLight(unsigned int index) {
			return (Light*)m_lightArray[index];
		}
		
        // Get all the triangles in the scene
        SceneObject *getSceneObjects() {
            return m_sceneObjList;
        }
        
        // Singleton Getters
        static SceneManager *getSingletonPtr() {
            return ms_singleton;
        }
        
        static SceneManager& getSingletonRef() {
            assert(ms_singleton != NULL);
            return *ms_singleton;
        }
	public:
		// Add objects to the scene
		void addTriangleList(const Triangle *triList, const size_t triCount);
		
    protected:
        
        // The root node of KD-Tree
        KDTreeNode *m_rootNode;
        
        // Nodes' list
        typedef list<KDTreeNode*> KDTreeNodeList;
        KDTreeNodeList m_nodeList;
        
		/*
        typedef Vector<SceneObject*> SceneObjectArray;
        SceneObjectArray m_sceneObjects;
 		*/

		// triangle buffer
		typedef std::vector<Triangle*> TrianlgeArray;
		TriangleArray m_triangleArray;
		
		typedef std::vector<Light*> LightArray;
		LightArray m_lightArray;
		
        SplitList *m_splitPool; 
        SplitList *m_splitList;
        
        // Axis-aligned bounding box for the entire scene
        AxisAlignedBox m_aabb;
        
    };
}

#endif
